#include "types.h"
#include "boundedbuffer.h"
#include "user.h"
#include "semaphore.h" 




void enter_item(struct BB* bb, void* element){

	bb->buffer[bb->index_of_last_element] = element;
	bb->index_of_last_element++;
}

void* remove_item(struct BB* bb){
	void * return_element = 0;
	int i = 0;
	if(bb->index_of_last_element <= 0){
		printf(1,"trying to remove from buffer but buffer is empty\n");
		return 0;
	}	
	else{
		return_element = bb->buffer[0];
		for(i = 1; i < bb->index_of_last_element; i++){
			bb->buffer[i-1] = bb->buffer[i];
		}
		bb->index_of_last_element--;
		return return_element;
	}
}



struct BB* BB_create(int max_capacity){

	int i;
	
	if(max_capacity <= 0){
		printf(1,"buffer size is less or equal to 0\n");
		return 0;
	
	}


	struct BB* bb = malloc(sizeof(struct BB));
	bb->capacity = max_capacity;
	bb->index_of_last_element = 0;
	for(i = 0; i < BUFF_SIZE; i++){
		bb->buffer[i] = 0;	
	}
	//initializing semaphores
	bb->binary_semaphore_id = binary_sem_create();
	bb->empty = semaphore_create(max_capacity);
	bb->full = semaphore_create(0);

	//checking for validation
	if((bb->binary_semaphore_id == -1) || (bb->empty == 0) || (bb->full == 0)){
		printf(1,"semaphores were not initialized correctly\n");
		return 0;
	}

	return bb;
} 

void semaphore_put(struct BB* bb, void* element){

	int error_check;	
	//printf(1, "semaphore put - Empty value before down is %d\n", bb->empty->value);
	sem_down(bb->empty); //check if & should be used
	//printf(1, "semaphore put - Empty value after down is %d\n", bb->empty->value);

	error_check = binary_sem_down(bb->binary_semaphore_id);
	if(error_check == -1){
		printf(1,"operation binary sem down has failed\n");
	}
	enter_item(bb, element);		
	//printf(1, "number of elements in buffer after inserting is %d\n", bb->index_of_last_element);

	error_check = binary_sem_up(bb->binary_semaphore_id);
	if(error_check == -1){
		printf(1,"operation binary sem up has failed\n");
	}
	//printf(1, "semaphore put - full value before up is %d\n", bb->full->value);
	sem_up(bb->full);
	//printf(1, "semaphore put - full value after up is %d\n", bb->full->value);
}


void* semaphore_pop(struct BB* bb){

	int error_check;;
	//printf(1, "semaphore_pop - full value before down is %d\n", bb->full->value);
	sem_down(bb->full);
	//printf(1, "semaphore_pop - full value after down is %d\n", bb->full->value);
	error_check = binary_sem_down(bb->binary_semaphore_id);
	if(error_check == -1){
		printf(1,"operation binary sem down has failed\n");
	}
	
	void* return_item = remove_item(bb);
	//printf(1, "number of elements in buffer after removing is %d\n", bb->index_of_last_element);
	
	error_check = binary_sem_up(bb->binary_semaphore_id);
	if(error_check == -1){
		printf(1,"operation binary sem up has failed\n");
	}
	//printf(1, "semaphore_pop - Empty value before up is %d\n", bb->empty->value);
	sem_up(bb->empty);
	//printf(1, "semaphore_pop - Empty value after up is %d\n", bb->empty->value);
	return return_item;
}

void destroy_buffer(struct BB* bb ){
        free(bb);
}


